package com.distribute.framework.core.sql.datasource;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;

import javax.sql.DataSource;

import com.distribute.framework.core.web.helper.WebHelper;
import com.distribute.framework.core.web.util.Lazy3qLogger;

public class Lazy3qDataSource implements DataSource
{
	String url;
	String driver;
	String username;
	String password;
	Integer max=5;
	Integer timeout=3;
	Integer idle=1800;
	Boolean autoCommit=true;
	
	Set<Lazy3qConnection> connection_pool=new HashSet();
	
	public Lazy3qDataSource()
	{
		super();
	}
	
	public Lazy3qDataSource(String url, String driver, String username,String password, Integer max, Integer timeout,Integer idle)
	{
		super();
		this.url = url;
		this.driver = driver;
		this.username = username;
		this.password = password;
		this.max = max;
		this.timeout = timeout;
		this.idle=idle;
	}

	public Connection getConnection() throws SQLException
	{
		return this.getConnection(username, password);
	}

	public Connection getConnection(String username, String password)throws SQLException
	{
		Lazy3qConnection conn=null;
		
		while(conn==null){//一直等待直到获取可用的连接		
			try{
				conn=getPoolConnection();
				if(conn!=null)
					return conn;				
				conn = createConnection(username,password);				
				if(conn!=null)			
					return conn;
			} catch (SQLException e){
				throw e;
			} catch (Exception e){
				throw new RuntimeException(e);
			}
			Lazy3qLogger.error("[size:"+connection_pool.size()+"][max:"+this.getMax()+"] 数据库链接池满，正在等待空闲的链接..");
			try{
				Thread.sleep(100);
			} catch (InterruptedException e){
				e.printStackTrace();
			}
		}
				
		return null;
	}

	private synchronized Lazy3qConnection createConnection(String _username, String _password) throws Exception
	{
		if(this.connection_pool.size()>=this.getMax())
			return null;
		
		Driver _driver=null;
		_driver = (Driver)Class.forName(this.getDriver()).newInstance();
		DriverManager.registerDriver(_driver);
		Class.forName(driver);
		DriverManager.setLoginTimeout(timeout);
		Connection con = DriverManager.getConnection(url, _username, _password);
		if(con==null)
			throw new Exception("无法根据["+url+"]["+_username+"]["+_password+"]创建链接");
		Lazy3qConnection conn=new Lazy3qConnection(con);
		final Lazy3qConnection final_conn = conn;
		final_conn.addConnectionEventListener(new Lazy3qConnectionListener(){
			public void connectionClosed(Lazy3qConnectionEvent event){
				final_conn.setUsered(false);
			}
		});
		conn.setAutoCommit(autoCommit);
		connection_pool.add(conn);
		conn.setUsered(true);
		return conn;
	}

	private synchronized Lazy3qConnection getPoolConnection() throws SQLException
	{
		Iterator<Lazy3qConnection> it = connection_pool.iterator();
		
		List<Lazy3qConnection> removes=new ArrayList();
		
		Lazy3qConnection conn=null;
		while(it.hasNext())
		{
			conn=it.next();
			if(conn.isUsered())
				continue;
			if(conn.isClosed())
			{	
				removes.add(conn);
				conn=null;
				continue;
			}
			if((new Date().getTime()-conn.getLast().getTime())/1000>idle)
			{
				removes.add(conn);
				conn=null;
				continue;
			}
			conn.setUsered(true);
			break;
		}
		
		for(Lazy3qConnection c:removes)
			connection_pool.remove(c);
		
		return conn;
	}

	public PrintWriter getLogWriter() throws SQLException
	{
		//  Auto-generated method stub
		return null;
	}
	
	public void setLogWriter(PrintWriter out) throws SQLException
	{
		//  Auto-generated method stub		
	}

	public int getLoginTimeout() throws SQLException
	{
		return this.timeout;
	}

	public void setLoginTimeout(int seconds) throws SQLException
	{
		this.timeout=seconds;
	}

	public String getUrl()
	{
		return url;
	}

	public void setUrl(String url)
	{
		this.url = url;
	}

	public String getDriver()
	{
		return driver;
	}

	public void setDriver(String driver)
	{
		this.driver = driver;
	}

	public String getUsername()
	{
		return username;
	}

	public void setUsername(String username)
	{
		this.username = username;
	}

	public String getPassword()
	{
		return password;
	}

	public void setPassword(String password)
	{
		this.password = password;
	}

	public Integer getMax()
	{
		return max;
	}

	public void setMax(Integer max)
	{
		this.max = max;
	}

	public Integer getIdle()
	{
		return idle;
	}

	public void setIdle(Integer idle)
	{
		this.idle = idle;
	}

	public Boolean getAutoCommit() {
		return autoCommit;
	}

	public void setAutoCommit(Boolean autoCommit) {
		this.autoCommit = autoCommit;
	}

	public <T> T unwrap(Class<T> iface) throws SQLException {
		//  Auto-generated method stub
		return null;
	}

	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		//  Auto-generated method stub
		return false;
	}

	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		// TODO Auto-generated method stub
		return null;
	}


}